package com.bub.pay.framework.common.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 反射工具类
 */
public class ReflectionUtil {

    /**
     * clazz关系缓存Map
     */
    private static Map<String, Boolean> clazzRelationPackageCacheMap = new HashMap<>();

    /**
     * clazz是否于@packageName有关系
     * 当clazz的父类在此packageName 下
     * 或clazz实现的接口在此packageName下
     * 则会返回true
     *
     * @param clazz       需要判断的clazz
     * @param packageName 包
     * @return 是否有关系
     */
    public static boolean clazzRelationPackage(Class clazz, String packageName) {
        String clazzName = clazz.getName();
        String clazzRelationKey = String.format("%s:%s", clazzName, packageName);
        Boolean cachedResult = clazzRelationPackageCacheMap.get(clazzRelationKey);
        if (cachedResult != null) {
            return cachedResult;
        }

        List<String> clazzNameList = new ArrayList<>();

        Class currentClass = clazz;
        while (currentClass != null && currentClass != Object.class) {
            // 添加当前class的接口到clazzNameList
            Class[] clazzInterfaces = currentClass.getInterfaces();
            for (Class clazzInterface : clazzInterfaces) {
                addInterfaceRelationPackage(clazzInterface,clazzNameList);
            }
            // 添加当前clazz到classNameList
            clazzNameList.add(currentClass.getName());
            // 当前class = 父级
            currentClass = currentClass.getSuperclass();
        }

        // 判断所有的clazzName是否与packageName相匹配
        for (String clazzNameForList : clazzNameList) {
            if (clazzNameForList.startsWith(packageName)) {
                clazzRelationPackageCacheMap.put(clazzRelationKey, true);
                return true;
            }
        }

        // 如果无关系则加入false
        clazzRelationPackageCacheMap.put(clazzRelationKey, false);
        return false;
    }

    /**
     * 添加接口的关系包
     *
     * @param clazzInterface 接口
     * @param clazzNameList  关系包存放list
     */
    private static void addInterfaceRelationPackage(Class clazzInterface, List<String> clazzNameList) {
        Class[] parentInterfaceList = clazzInterface.getInterfaces();
        for (Class parentInterface : parentInterfaceList) {
            addInterfaceRelationPackage(parentInterface, clazzNameList);
        }
        clazzNameList.add(clazzInterface.getName());
    }

}
